#include <MGLib.h>

// GLUT CALLBACK functions ////////////////////////////////////////////////////
void displayCB();
void reshapeCB(int w, int h);
void timerCB(int millisec);
void idleCB();
void keyboardCB(unsigned char key, int x, int y);
void keyboardUpCB(unsigned char key, int x, int y);
void mouseCB(int button, int stat, int x, int y);
void mouseMotionCB(int x, int y);

// constants
const int SCREEN_WIDTH = 1024;
const int SCREEN_HEIGHT = 1024;

// global variables
Timer timer;

///////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
    // GLUT stuff for windowing
    // initialization openGL window.
    // It must be called before any other GLUT routine.
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_ALPHA);   // display mode

    glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);              // window size

    glutInitWindowPosition(100, 100);                           // window location

    // finally, create a window with openGL context
    // Window will not displayed until glutMainLoop() is called
    // It returns a unique ID.
    int handle = glutCreateWindow(argv[0]);     // param is the title of window

	if( glewInit() != GLEW_OK )
	{
		return -1;
	}

    atexit(MGL_exit);
    glutDisplayFunc(displayCB);
    //glutTimerFunc(33, timerCB, 33);
    glutIdleFunc(idleCB);
    glutReshapeFunc(reshapeCB);
    glutKeyboardFunc(keyboardCB);
	glutKeyboardUpFunc(keyboardUpCB);
    glutMouseFunc(mouseCB);
    glutMotionFunc(mouseMotionCB);

	MGL_init();

    timer.start();
	Application::GetInstance();
	Application::GetInstance()->SetResolution( SCREEN_WIDTH, SCREEN_HEIGHT );
	Application::GetInstance()->SetRunArguments( argc, argv );

	// the last GLUT call (LOOP)
    // window will be shown and display callback is triggered by events
    // NOTE: this call never return main().
    glutMainLoop(); /* Start GLUT event-processing loop */

    return 0;
}


//=============================================================================
// CALLBACKS
//=============================================================================

void displayCB()
{
	timer.sleepTimeInMilliSec( Application::GetInstance()->GetFrameTimeLimit() );
	f32 dt = (f32) timer.getElapsedTimeInMilliSec();
	timer.start();

	Application::GetInstance()->Update( dt );

    glutSwapBuffers();
}

void reshapeCB(int width, int height)
{
    Application::GetInstance()->SetResolution( width, height );
}

void timerCB(int millisec)
{
    glutTimerFunc(millisec, timerCB, millisec);
    glutPostRedisplay();
}

void idleCB()
{
	//TDDO fps limiter
    glutPostRedisplay();
}

void keyboardCB(unsigned char key, int x, int y)
{
	InputManager::GetInstance()->GetInput( true, key, x, y );
}

void keyboardUpCB(unsigned char key, int x, int y)
{
	InputManager::GetInstance()->GetInput( false, key, x, y );
}

void mouseCB(int button, int state, int x, int y)
{
	InputManager::GetInstance()->GetMouseClick( button, state == GLUT_DOWN, x, y );
}

void mouseMotionCB(int x, int y)
{
	InputManager::GetInstance()->GetMouseMove( x, y );
}
